package ar.edu.utn.frba.disenio;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;

import ar.edu.utn.frba.disenio.exceptions.NoExisteReservaException;
import ar.edu.utn.frba.disenio.exceptions.NoSePuedeComprarException;
import ar.edu.utn.frba.disenio.exceptions.NoSePuedeReservarException;
import ar.edu.utn.frba.disenio.exceptions.ReservaExistenteException;

public class ReservasManager
{
	private Map<Reserva,LinkedList<Reserva>> reservaception = new HashMap<Reserva,LinkedList<Reserva>>();
	
	
	public void ValidarReserva(Asiento asiento,Usuario usuario)
	{
		for(Reserva reserva : getReservaception().keySet())
		{
			if(reserva.getAsiento().getCodigo().equals(asiento.getCodigo()) && reserva.getUsuario().equals(usuario))
			{		
				throw new NoSePuedeReservarException("Ya ha reservado este asiento.");
			}
			if(reserva.getAsiento().getCodigo().equals(asiento.getCodigo()))
			{		
				throw new ReservaExistenteException("Hay una reserva de otro usuario para este asiento.");
			}
		}
	}
	
	public void reservar(Asiento asiento,Usuario usuario)
	{
		Reserva reserva = new Reserva();
		reserva.setAsiento(asiento);
		reserva.setUsuario(usuario);
		getReservaception().put(reserva, new LinkedList<Reserva>());
		asiento.setReservado(true);
	}
	
	public void ValidarSobrereserva(Asiento asiento,Usuario usuario)
	{
		for(Reserva reserva : getReservaception().keySet())
		{
			if(reserva.getAsiento().getCodigo().equals(asiento.getCodigo()) && reserva.getUsuario().equals(usuario) && asiento.getReservado())
			{		
				throw new NoSePuedeReservarException("Ya ha reservado este asiento.");
			}
		}
		
		for(Reserva sobrereserva : this.getSobreReservas(asiento))
		{
			if(sobrereserva.getUsuario().equals(usuario))
			{
				throw new NoSePuedeReservarException("Ya ha sobreservado este asiento.");
			}
		}
	}
	
	public void sobrereservar(Asiento asiento,Usuario usuario)
	{
		Reserva sobreReserva = new Reserva();
		sobreReserva.setAsiento(asiento);
		sobreReserva.setUsuario(usuario);
		this.getSobreReservas(asiento).addLast(sobreReserva);	
	}
	
	public void controlDeVentaDeReserva(Asiento asiento,Usuario usuario)
	{
		try 
		{
			Reserva reserva = this.getReserva(asiento);
			if(!reserva.getUsuario().equals(usuario))
			{
				throw new NoSePuedeComprarException("Hay una reserva de otro usuario para este asiento.");
			}
		} catch (NoExisteReservaException e) {
			//El usuario esta habilitado para comprar
			return;
		}
	}
	
	public void comprarReserva(Asiento asiento,Usuario usuario)
	{
		for(Reserva reserva : getReservaception().keySet())
		{
			if(reserva.getAsiento().getCodigo().equals(asiento.getCodigo()))
			{				
				if(usuario.equals(reserva.getUsuario()))
				{
					getReservaception().remove(reserva);
					asiento.setReservado(false);
					return;
				}
			}
		}
	}
	
	public void cancelarReservacion(Asiento asiento,Usuario usuario)
	{
		for(Reserva reserva : getReservaception().keySet())
		{
			if(reserva.getAsiento().getCodigo().equals(asiento.getCodigo()))
			{				
				if(usuario.equals(reserva.getUsuario()))
				{
					//Se quiere cancelar la reserva.
					LinkedList<Reserva> sobreReservas = getReservaception().get(reserva);
					if(!sobreReservas.isEmpty())
					{
						Reserva nuevaReserva = sobreReservas.getFirst();
						sobreReservas.remove(nuevaReserva);
						getReservaception().put(nuevaReserva, sobreReservas);
					} 
					else 
					{
						asiento.setReservado(false);
					}
					
					getReservaception().remove(reserva);
				}
				else
				{
					//Se quiere cancelar una sobrereserva.
					LinkedList<Reserva> listaReservas = reservaception.get(reserva);
					this.cancelarSobrereserva(asiento, usuario, listaReservas);
				}
				return;
			}
		}
	}
	
	private void cancelarSobrereserva(Asiento asiento, Usuario usuario, LinkedList<Reserva> listaReservas) 
	{
		for(Reserva reserva : new LinkedList<Reserva>(listaReservas))
		{
			if(reserva.getAsiento().equals(asiento) && reserva.getUsuario().equals(usuario))
			{
				listaReservas.remove(reserva);
			}
		}
	}

	
	public Reserva getReserva(Asiento asiento)
	{
		for(Reserva reserva : getReservaception().keySet())
		{
			if(reserva.getAsiento().getCodigo().equals(asiento.getCodigo()))
			{				
				return reserva;
			}
		}
		throw new NoExisteReservaException("No existe ninguna reserva para el asiento.");
	}
	
	public LinkedList<Reserva> getSobreReservas(Asiento asiento)
	{
		Reserva reserva  = this.getReserva(asiento);
		return reservaception.get(reserva);
	}



	public Map<Reserva,LinkedList<Reserva>> getReservaception() {
		return reservaception;
	}

	public void setReservaception(Map<Reserva,LinkedList<Reserva>> reservaception) {
		this.reservaception = reservaception;
	}



}
